package appModel;

import globalTools.FoldersPaths;
import globalTools.Savable;
import gridModel.EditableGridModel;
import gridModel.GridSize;
import gridModel.StdEditableGridModel;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

/**
 * Collection des grilles du jeu.
 * A consulter pour les proposer au jeu.
 */
public class GridsCollection extends Savable implements FoldersPaths {
	
	public static class Quota {
		private int done, total;
		public Quota(int done, int total) {
			this.done = done;
			this.total = total;
		}
		public int done() { return done; }
		public int total() { return total; }
		public void incDone() { done++; }
		public void incTotal() { total++; }
		public void add(Quota q) {
			done += q.done;
			total += q.total;
		}
		public String toString() {
			return done + "/" + total;
		}
	}
	
	public static enum Categories {
		CLASSICS(1),
		DIVERS(1),
		POKEMON(3);
		
		// ATTRIBUTS
		
		private int level;
		
		// CONSTRUCTEUR
		
		private Categories(int level) {
			this.level = level;
		}
		
		// REQUETES
		
		public int getLevel() {
			return level;
		}
	}
	
	// ATTRIBUTS
	
	private static final long serialVersionUID = 1L;
	
	private SortedMap<Categories, SortedMap<GridSize, List<String>>> collection;
	
	// CONSTRUCTEUR
	
	private GridsCollection() {
		super(GRIDS_FOLDER + LIBRARY_FILENAME.substring(1));
		collection = new TreeMap<Categories, SortedMap<GridSize, List<String>>>();
		for (Categories c : Categories.values()) {
			collection.put(c, new TreeMap<GridSize, List<String>>());
		}
	}
	
	// REQUETES
	
	public Quota getSize() throws IOException {
		return getSize(StdSaveData.getSavedData());
	}
	
	private Quota getSize(SaveData scores) {
		Quota res = new Quota(0, 0);
		for (Categories c : Categories.values()) {
			res.add(getSize(c, scores));
		}
		return res;
	}
	
	public Quota getSize(Categories c) throws IOException {
		return getSize(c, StdSaveData.getSavedData());
	}
	
	private Quota getSize(Categories c, SaveData scores) {
		Quota res = new Quota(0, 0);
		for (GridSize g : collection.get(c).keySet()) {
			res.add(getSize(c, g, scores));
		}
		return res;
	}
	
	public Quota getSize(Categories c, GridSize g) throws IOException {
		return getSize(c, g, StdSaveData.getSavedData());
	}
	
	private Quota getSize(Categories c, GridSize g, SaveData scores) {
		Quota res = new Quota(0, 0);
		if (collection.get(c).get(g) != null) {
			for (String s : collection.get(c).get(g)) {
				if (scores.getScore(s) != null) {
					res.incDone();
				}
				res.incTotal();
			}
		}
		return res;
	}
	
	public Set<String> getTotalGrids() {
		Set<String> res = new HashSet<String>();
		for (Categories c : Categories.values()) {
			for (GridSize g : collection.get(c).keySet()) {
				res.addAll(collection.get(c).get(g));
			}
		}
		return res;
	}
	
	public SortedMap<GridSize, List<String>> getGridsGroup(Categories c) {
		return new TreeMap<GridSize, List<String>>(collection.get(c));
	}
	
	public List<String> getGrids(Categories c, GridSize g) {
		if (collection.get(c).get(g) == null) {
			return null;
		}
		return new ArrayList<String>(collection.get(c).get(g));
	}
	
	public static GridsCollection getGridsCollection(Object o) {
		GridsCollection c = (GridsCollection) Savable.getSaved(LIBRARY_FILENAME, o);
		return (c == null) ? new GridsCollection() : c;
	}
	
	public boolean isEmpty(Categories c) {
		for (GridSize s : collection.get(c).keySet()) {
			if (collection.get(c).get(s) != null) {
				return false;
			}
		}
		return true;
	}
	
	public boolean isEmpty(Categories c, GridSize s) {
		return collection.get(c).get(s) == null;
	}
	
	// COMMANDES
	
	public void putGrid(Categories c, String fileName) throws IOException {
		if (fileName == null) {
			throw new IllegalArgumentException();
		}
		if (fileName != null) {
			EditableGridModel m = StdEditableGridModel.getGridModel(this, fileName);
			GridSize g = new GridSize(m.getWidth(), m.getHeight());
			if (collection.get(c).get(g) == null) {
				collection.get(c).put(g, new ArrayList<String>());
			}
			collection.get(c).get(g).add(fileName);
			save();
		}
	}
	
	public void reset() throws IOException {
		for (Categories c : Categories.values()) {
			collection.get(c).clear();
		}
		save();
	}

}
